﻿namespace Raven
{
    public class Regulator
    {
        //the time period between updates 
        private Fix _updatePeriod;

        //the next time the regulator allows code flow
        private Fix _nextUpdateTime;

        private RavenGame _world;

        public Regulator(RavenGame world, int NumUpdatesPerSecondRqd)
        {
            _world = world;
            _nextUpdateTime = _world.GetTimer().currentTime + _world.GetRandom().RandFix();

            if (NumUpdatesPerSecondRqd > 0)
            {
                _updatePeriod = Fix.One / NumUpdatesPerSecondRqd;
            }

            else if (NumUpdatesPerSecondRqd == 0)
            {
                _updatePeriod = Fix.Zero;
            }

            else if (NumUpdatesPerSecondRqd < 0)
            {
                _updatePeriod = -1;
            }
        }

        //returns true if the current time exceeds m_dwNextUpdateTime
        public bool isReady()
        {
            //if a regulator is instantiated with a zero freq then it goes into
            //stealth mode (doesn't regulate)
            if (_updatePeriod == 0)
            {
                return true;
            }

            //if the regulator is instantiated with a negative freq then it will
            //never allow the code to flow
            if (_updatePeriod < 0)
            {
                return false;
            }


            Fix CurrentTime = _world.GetTimer().currentTime;

            //the number of milliseconds the update period can vary per required
            //update-step. This is here to make sure any multiple clients of this class
            //have their updates spread evenly
            Fix interval = 3;
            Fix UpdatePeriodVariator = interval / _world.GetTimer().frameCount;

            if (CurrentTime >= _nextUpdateTime)
            {
                _nextUpdateTime = CurrentTime + _updatePeriod +
                                  _world.GetRandom().RandInRange(-UpdatePeriodVariator, UpdatePeriodVariator);

                return true;
            }

            return false;
        }
    }
}